package com.msun.auth.apiAdmin;

import com.msun.auth.custom.annotation.ContextWithToken;
import com.msun.auth.custom.annotation.WithoutToken;
import com.msun.auth.custom.constants.CustomConsts;
import com.msun.auth.custom.constants.RoleLevels;
import com.msun.auth.custom.exception.BizException;
import com.msun.auth.custom.exception.BizResultCode;
import com.msun.auth.utils.IpUtils;
import com.msun.auth.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;

@Slf4j
@Component
public class AdminContextInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String ip = IpUtils.getIpAddr(request);
        boolean mustCheck = false;
        AdminContext.Context ctx = new AdminContext.Context();
        ctx.setIp(ip);
        if (handler instanceof HandlerMethod) {
            Method method = ((HandlerMethod) handler).getMethod();
            if (!method.isAnnotationPresent(WithoutToken.class)) {
                if (method.getDeclaringClass().isAnnotationPresent(ContextWithToken.class)) {
                    ContextWithToken contextWithToken = method.getDeclaringClass().getAnnotation(ContextWithToken.class);
                    if (contextWithToken.requiredToken()) {
                        mustCheck = true;
                    }
                } else if (method.isAnnotationPresent(ContextWithToken.class)) {
                    ContextWithToken contextWithToken = method.getAnnotation(ContextWithToken.class);
                    if (contextWithToken.requiredToken()) {
                        mustCheck = true;
                    }
                }
            }
        }
        String token = request.getHeader(CustomConsts.TOKEN);
        if (StringUtils.isNotBlank(token) && !StringUtils.equals("init", token)) {
            try {
                Map<String, Object> tokenInfo = JwtUtils.parseToken(token, CustomConsts.SIGN_KEY);
                ctx.setUid(Long.parseLong(String.valueOf(tokenInfo.get(CustomConsts.UID))));
                ctx.setUname(String.valueOf(tokenInfo.getOrDefault(CustomConsts.UNAME, "")));
                ctx.setName(String.valueOf(tokenInfo.getOrDefault(CustomConsts.NAME, "")));
                ctx.setAppId(Long.parseLong(String.valueOf(tokenInfo.getOrDefault(CustomConsts.APP_ID, "0"))));
                ctx.setGroupId(Long.parseLong(String.valueOf(tokenInfo.getOrDefault(CustomConsts.GROUP_ID, "0"))));
                int roleLevel = Integer.parseInt(String.valueOf(tokenInfo.getOrDefault(CustomConsts.ROLE_LEVEL, "0")));
                if (roleLevel < RoleLevels.APP_ADMIN) {
                    throw new BizException(BizResultCode.NoRight);
                }
                ctx.setRoleLevel(roleLevel);

            } catch (Exception e) {
                e.printStackTrace();
                if (mustCheck) {
                    throw new BizException(BizResultCode.InvalidToken, "无效签名1");
                }
            }
        } else {
            if (mustCheck) {
                throw new BizException(BizResultCode.InvalidToken, "无效签名2");
            }
        }
        AdminContext.set(ctx);
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        AdminContext.remove();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
